/*
 * ========THE SOLMIX PROJECT=====================================
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.gnu.org/licenses/ 
 * or see the FSF site: http://www.fsf.org. 
 */
package org.solmix.fmk.config.impl;

import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.solmix.commons.io.SlxFile;
import org.solmix.commons.logs.Logger;
import org.solmix.commons.util.DataUtil;

/**
 * @author solomon
 * @since 0.0.1
 * @version $ID$  2011-2-6 solmix-config 
 */
public class ConfigLoader
{
   private static Logger log = new Logger(ConfigLoader.class.getName());
   public static String framework = "framework.properties";

   public static String frameworkDevenv = "devenv.framework.properties";

   public static String project = "project.properties";

   public static String devenv = "devenv.properties";

  public static String interfaces = "interfaces.properties";

   public static String server = "server.properties";

   ConfigLoader()
   {
   }

   public Map<String, Object> loadConfig() throws Exception
   {
      Map<String, Object> accumulator = Collections.synchronizedMap(new HashMap<String, Object>());
      try {
         loadAndMerge(framework, "CLASSPATH", accumulator);
      } catch (Exception e) {
         throw new Error((new StringBuilder())
            .append("Can't find framework.properties - unable to proceed.  Please add this file to your classpath and try again.  Actual error: ")
            .append(e.toString()).toString());
      }
      try {
         loadAndMerge(project, "CLASSPATH", accumulator);
      } catch (Exception ignored) {
      }
      try {
         loadAndMerge(frameworkDevenv, "CLASSPATH", accumulator, true, true);
      } catch (Exception ignored) {
      }
      try {
         loadAndMerge(devenv, "CLASSPATH", accumulator, true, true);
      } catch (Exception ignored) {
      }
      try {
         loadAndMerge(interfaces, "CLASSPATH", accumulator, true, true);
      } catch (Exception ignored) {
      }
      try {
         loadAndMerge(server, "CLASSPATH", accumulator);
      } catch (Exception ignored) {
         String webRoot = null;
         if (accumulator.get("webRoot") == null)
            webRoot = "__USE_CONTAINER__";
         else if (accumulator.get("webRoot").equals("__AUTODETECT__"))
            webRoot = "__USE_CONTAINER__";
         String configPath = (new StringBuilder()).append(webRoot).append("/WEB-INF/classes").toString();
         try {
            loadAndMerge(server, configPath, accumulator);
         } catch (Exception ignored2) {
            log.info((new StringBuilder()).append("Unable to load ").append(server).toString());
         }
      }
      return accumulator;
   }

   /**
    * @param fileName
    * @param fileLocation
    * @param accumulator
    * @param suppressLog
    * @param useJavaPropertyLoader
    */
   private void loadAndMerge(String fileName, String fileLocation, Map<String, Object> accumulator,
      boolean suppressLog, boolean useJavaPropertyLoader) throws Exception
   {
      if (!suppressLog)
         log.info((new StringBuilder()).append("Attempting to load ").append(fileName).append(" from ")
            .append(fileLocation).toString());
      String _loadedFromLocation = null;
      InputStream _is = null;
      String _loadedFilename = null;
      SlxFile _file = null;
      if (fileLocation.equals("CLASSPATH"))
         _file = new SlxFile(DataUtil.resourceFromClassLoader(ConfigLoader.class, fileName));
      else {
         String path = fileName;
         if (!fileLocation.equals(""))
            path = (new StringBuilder()).append(fileLocation).append("/").append(fileName).toString();
         _file = new SlxFile(path);
      }
      if (_file.exists()) {
         _loadedFilename = _file.getCanonicalPath();
         _is = _file.getInputStream();
         _loadedFromLocation =
            (new StringBuilder()).append(_loadedFromLocation).append(" at location: ").append(_loadedFilename)
               .toString();
      } else {
         if (!suppressLog)
            log.info((new StringBuilder()).append("Unable to locate ").append(fileName).append(" in ")
               .append(fileLocation).toString());
         throw new Exception((new StringBuilder()).append("File not found: ").append(fileName).toString());
      }
      Map<String, Object> thisConfig = new HashMap<String, Object>();
      if (useJavaPropertyLoader) {
         Properties props = new Properties();
         props.load(_is);
         for ( Object key : props.keySet() )
         {
            thisConfig.put( key.toString(), props.getProperty( key.toString() ).trim() );
         }

      }
      if (_is != null)
         _is.close();
      DataUtil.mapMerge(thisConfig, accumulator);
   }

   /**
    * @param fileName
    * @param fileLocation
    * @param accumulator
    * @throws Exception
    */
   private void loadAndMerge(String fileName, String fileLocation, Map<String, Object> accumulator) throws Exception
   {
      loadAndMerge(fileName, fileLocation, accumulator, false, true);
   }
}
